DynamoDBで特定項目の有無を調べる
DynamoDBを使っていると、「特定の項目がxxx
のデータがある? ない?」と調べたくなる場合があります。
たくさんある全データをscan()
して判断するのは大変なので、今回は、GSIを使う方法を試してみました。
例えば、写真のメタデータを管理するDynamoDBテーブル
写真のメタデータを管理するDynamoDBテーブルを例とします。
photoId | s3Bucket | s3Key | place |
---|---|---|---|
p0001 | my-photo-bucket | foo/bar/aaa.jpg | Tokyo |
p0002 | my-photo-bucket | foo/bar/bbb.jpg | Iwate |
p0003 | my-photo-bucket | foo/bar/ccc.jpg | Osaka |
p0004 | my-photo-bucket | foo/bar/ddd.jpg | Tokyo |
p0005 | my-photo-bucket | foo/bar/eee.jpg | Fukuoka |
このとき、下記を調べたい例です。
place
がTokyo
のデータはある?ない?place
がAmerica
のデータはある?ない?
DynamoDBテーブルを準備する
CloudFormationテンプレート
place
でGSIを作成しています。有無を知りたいだけなので、GSIはKEYS_ONLY
を使います。
AWSTemplateFormatVersion: '2010-09-09' Description: DynamoDB Sample Resources: DemoTable: Type: AWS::DynamoDB::Table Properties: TableName: photo-meta-table BillingMode: PAY_PER_REQUEST AttributeDefinitions: - AttributeName: photoId AttributeType: S - AttributeName: place AttributeType: S KeySchema: - AttributeName: photoId KeyType: HASH GlobalSecondaryIndexes: - IndexName: place-index KeySchema: - AttributeName: place KeyType: HASH Projection: ProjectionType: KEYS_ONLY
デプロイ
aws cloudformation deploy \ --template-file dynamodb.yaml \ --stack-name DynamoDB-Photo-Meta-Sample-Stack \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset
DynamoDBの特定項目の有無を調べる
サンプルコード
下記のPythonコードのように調べることができます。
import boto3 from boto3.dynamodb.conditions import Key def main(): dybamodb = boto3.resource('dynamodb') res = is_exist_place('Tokyo', dybamodb) print(res) def is_exist_place(place: str, dynamodb) -> bool: table = dynamodb.Table('photo-meta-table') options = { 'IndexName': 'place-index', 'Select': 'COUNT', 'KeyConditionExpression': Key('place').eq(place), 'Limit': 1, } res = table.query(**options) if res.get('Count', 0) != 0: return True return False if __name__ == '__main__': main()
今回、調べたい項目(place
)をGSIのパーティションキーに設定しています。たとえば、GSIのパーティションキーにTokyo
を指定してquery()
を実行すれば、place==Tokyo
のデータのみを取得できます。そのため、「ある? ない?」を判断するためには、Limit=1
を指定すれば十分です。全検索をする必要が無いので、とてもシンプルです。
Tokyoが2つあるとき
Tokyo
が2つあるときに調べると、True
が得られます。
$ python app.py True
Tokyoが1つあるとき
Tokyo
が1つあるときに調べると、True
が得られます。
$ python app.py True
Tokyoが無いとき
Tokyo
がないときに調べると、False
が得られます。
$ python app.py False
Tokyoがあって、placeが無い項目もある
True
が得られます。
$ python app.py True
Tokyoが無くて、placeが無い項目もある
False
が得られます。
$ python app.py False
さいごに
「1つでもxxx
があれば、AAAの処理をする」みたいな処理を作る必要があったので試してみました。
簡単にできて良かったです。